1 module lib.cmake; 2 3 import std.file : getcwd, mkdirRecurse; 4 import std.path : buildPath, absolutePath; 5 import std.process : environment; 6 import std..string : indexOf; 7 import std.regex : ctRegex, matchFirst; 8 9 import lib.set_compiler; 10 import lib.process : executeAt; 11 12 /** The options used for CMake */ 13 struct CmakeOptions 14 { 15 /** The build config. Defaults to `"release"` */ 16 string buildConfig = "release"; 17 /** The generator to use. Defaults to `"Ninja"` */ 18 auto generator = "Ninja"; 19 /** The compiler to use. If `CC` and `CXX` environment variables are not specified, it defaults to `clang` */ 20 auto compiler = "clang"; 21 } 22 23 /** 24 Configure and build a Cmake project at the given paths. 25 26 Params: 27 rootDir = The root path which includes CMakeLists.txt 28 buildDir = The building directory path 29 options = The options used for CMake 30 31 */ 32 void cmake(string rootDir = getcwd(), string buildDir = buildPath(getcwd(), 33 "./build"), CmakeOptions options = CmakeOptions()) 34 { 35 // build dir 36 mkdirRecurse(buildDir); 37 38 // env variables 39 string[string] env = set_compiler(options.compiler); 40 41 // sanitizer 42 const sanitizerArgs = convert_sanitizer(options.buildConfig); 43 44 // configure 45 executeAt(["cmake", "-G", options.generator, "-S", rootDir, "-B", 46 buildDir] ~ sanitizerArgs, rootDir, env); 47 // build 48 executeAt([ 49 "cmake", "--build", buildDir, "--config", 50 convert_build_config(options.buildConfig) 51 ], rootDir, env); 52 } 53 54 /** Convert D config to Cmake config */ 55 private auto convert_build_config(string buildConfig) 56 { 57 if (buildConfig.indexOf("debug") != -1) 58 { 59 return "Debug"; 60 } 61 else if (buildConfig.indexOf("release") != -1) 62 { 63 return "Release"; 64 } 65 66 return "Debug"; 67 } 68 69 private auto convert_sanitizer(string buildConfig) 70 { 71 // extract the name of the sanitizer from the build config and store it in the SANITIZER env variable for CMake to use. 72 auto sanitizeMatch = matchFirst(buildConfig, ctRegex!(r"sanitize-(\w*)")); 73 if (!sanitizeMatch.empty() && sanitizeMatch.length == 2) 74 { 75 return ["-D", "CMAKE_SANITIZER=" ~ sanitizeMatch[1]]; 76 } 77 78 return []; 79 }